---
title: 'User Components'
description: 'Easily extend your content page more interactive'
order: 1
---

import { Aside, Tabs, TabItem, MdxRepl } from 'astro-pure/user'

Components let you easily reuse a piece of UI or styling consistently. You can use them not just in `.astro` files, but also in `.mdx` files.

<Aside type='tip'>
[MDX](https://mdxjs.com/) is a format that lets you write JSX embedded inside Markdown. And it has no difference with markdown files in other ways.
</Aside>

For `.astro`, you can directly import and use components and use. An example will also shown in the first section.

<Aside type='tip'>
If you always import some components in your contents, you can use [astro-auto-import](https://github.com/delucis/astro-auto-import/tree/main/packages/astro-auto-import) to automatically import them instead of manually importing them in every file.
</Aside>

## Containers

### Card

<MdxRepl>
import { Card } from 'astro-pure/user'

<Card
  as='a'
  href='#card'
  heading='Lorem ipsum'
  subheading='Lorem ipsum dolor sit amet, vidit suscipit at mei.'
  date='August 2021'
>
  You can even contain a list here
</Card>

<Tabs slot='desc'>
<TabItem label='MDX'>
```jsx
import { Card } from 'astro-pure/user'

<Card
  as='a'
  href='#card'
  heading='Lorem ipsum'
  subheading='Lorem ipsum dolor sit amet, vidit suscipit at mei.'
  date='August 2021'
>
  You can even contain a list here
</Card>
```
</TabItem>
<TabItem label='Astro'>
```astro
---
import { Card } from 'astro-pure/user'
---
<!-- ... -->
<Card
  as='a'
  href='#card'
  heading='Lorem ipsum'
  subheading='Lorem ipsum dolor sit amet, vidit suscipit at mei.'
  date='August 2021'
>
  You can even contain a list here
</Card>
```
</TabItem>
</Tabs>
</MdxRepl>

### Collapse

<MdxRepl>
import { Collapse } from 'astro-pure/user'

<Collapse title='Lorem ipsum'>Lorem ipsum dolor sit amet, vidit suscipit at mei.</Collapse>
<Collapse title='Lorem ipsum'>
  <div slot='before' class='mt-2'>Are you sure you want to see?</div>
  <div>Lorem ipsum dolor sit amet, vidit suscipit at mei.</div>
</Collapse>

<Fragment slot='desc'>
```jsx
import { Collapse } from 'astro-pure/user'

<Collapse title='Lorem ipsum'> Lorem ipsum dolor sit amet, vidit suscipit at mei. </Collapse>
<Collapse title='Lorem ipsum'>
  <div slot='before' class='mt-2'>Are you sure you want to see?</div>
  <div>Lorem ipsum dolor sit amet, vidit suscipit at mei.</div>
</Collapse>
```
</Fragment>
</MdxRepl>

### Aside

<MdxRepl width='100%'>
<Aside>No type selected will default to 'note'. 😉</Aside>
<Aside type="tip">
Other content is also supported in aside! 😍

```js
// A code snippet, for example.
```
</Aside>
<Aside type='caution' title='You should know it!'>Is your code buggy again? 🤨</Aside>
<Aside type='danger'>Have you used `rm -rf` to clean your computer? 😡</Aside>

<Fragment slot='desc'>
  ```jsx
  import { Aside } from 'astro-pure/user'

  <Aside>No type selected will default to 'note'. 😉</Aside>
  <Aside type="tip">
  Other content is also supported in aside! 😍

  // ```js
  // A code snippet, for example.
  // ```
  </Aside>
  <Aside type='caution' title='You should know it!'>Is your code buggy again? 🤨</Aside>
  <Aside type='danger'>Have you used `rm -rf` to clean your computer? 😡</Aside>
  ```
</Fragment>
</MdxRepl>

This component also has a remark support version (which can directly use in `.md`), but not integrated in this theme. You can check [packages/starlight/integrations/asides.ts](https://github.com/withastro/starlight/blob/main/packages/starlight/integrations/asides.ts) for reference code.

```md
:::tip
This theme author is a good guy.
:::
```

### Tabs

<MdxRepl width='80%'>
<Tabs>
  <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem>
  <TabItem label="Moons">Io, Europa, Ganymede</TabItem>
</Tabs>

<Fragment slot='desc'>
  ```jsx
  import { Tabs, TabItem } from 'astro-pure/user';

  <Tabs>
    <TabItem label="Stars">Sirius, Vega, Betelgeuse</TabItem>
    <TabItem label="Moons">Io, Europa, Ganymede</TabItem>
  </Tabs>
  ```
</Fragment>
</MdxRepl>

### MDX Repl

<MdxRepl>
  <MdxRepl width='100%'>
  <p>Hello</p>
  <Fragment slot='desc'>
    ```html
    <p>Hello</p>
    ```
  </Fragment>
  </MdxRepl>

<Fragment slot='desc'>
  ````jsx
  import { MdxRepl } from 'astro-pure/user'

  // Width is optional; using width parameter to set
  // all elements inside the MDX Repl component.
  // (slot desc is not included this parameter)
  <MdxRepl width='100%'>
  <p>Hello</p>
  <Fragment slot='desc'>
    ```html
    <p>Hello</p>
    ```
  </Fragment>
  </MdxRepl>
  ````
</Fragment>
</MdxRepl>

You can combine any other components for the sclot `desc`. And `<Fragment>` will not be rendered as a parent html container tag.

## List

### CardList

<MdxRepl width='80%'>
import { CardList } from 'astro-pure/user'

<CardList title='A list' list={
  [{title: 'I am hidden!'}]
} collapse />
<CardList title='A list' list={
  [
    { title: 'Lorem ipsum', link: '#list' },
    { title: 'Dolor sit amet', children: [{
      title: 'Vidit suscipit', link: '#'
    }] }
  ]
} />

<Fragment slot='desc'>
  ```jsx
  import { CardList } from 'astro-pure/user'

  <CardList title='A list' list={
    [{title: 'I am hidden!'}]
  } collapse />
  <CardList title='A list' list={
    [
      { title: 'Lorem ipsum', link: '#list' },
      { title: 'Dolor sit amet', children: [{
        title: 'Vidit suscipit', link: '#'
      }] }
    ]
  } />
  ```
</Fragment>
</MdxRepl>

### Timeline

<MdxRepl>
import { Timeline } from 'astro-pure/user'

<Timeline events={
  [
    { date: 'August 2021', content: 'Hello' },
    { date: 'August 2022', content: '<i>World!</i>' },
  ]
} />

<Fragment slot='desc'>
  ```jsx
  import { Timeline } from 'astro-pure/user'

  <Timeline events={
    [
      { date: 'August 2021', content: 'Hello' },
      { date: 'August 2022', content: '<i>World!</i>' },
    ]
  } />
  ```
</Fragment>
</MdxRepl>

### Steps

<MdxRepl width='80%'>
<div>
import { Steps } from 'astro-pure/user'

How to Yi Jian San Lian:

<Steps>
1. Dian Zan
2. Tou Bi
3. Shou Cang

   Or GuanZhu sometimes.
</Steps>
</div>

<Fragment slot='desc'>
  ```jsx
  import { Steps } from 'astro-pure/user'

  How to Yi Jian San Lian:

  <Steps>
  1. Dian Zan
  2. Tou Bi
  3. Shou Cang
    
    Or GuanZhu sometimes.
  </Steps>
  ```
</Fragment>
</MdxRepl>

## Simple Text Render

### Button

<MdxRepl>
import { Button } from 'astro-pure/user'

<div class='flex gap-x-2'>
  <Button as='div' title='Simple' />
  <Button as='a' href='#button' title='Link style' variant='ahead' class='not-prose' />
  <Button as='div' title='Back' variant='back' />
  <Button as='div' title='Pill style' variant='pill' />
  <Button as='div' variant='pill'><i>Italic</i></Button>
</div>

<Fragment slot='desc'>
  ```jsx
  import { Button } from 'astro-pure/user'

  <div class='flex gap-x-2'>
    <Button as='div' title='Simple' />
    <Button as='a' href='#button' title='Link style' variant='ahead' class='not-prose' />
    <Button as='div' title='Back' variant='back' />
    <Button as='div' title='Pill style' variant='pill' />
    <Button as='div' variant='pill'><i>Italic</i></Button>
  </div>
  ```
</Fragment>
</MdxRepl>

### Spoiler

<MdxRepl>
import { Spoiler } from 'astro-pure/user'

<Spoiler>No one can find me.</Spoiler> But I am exposed here.

<Fragment slot='desc'>
  ```jsx
  import { Spoiler } from 'astro-pure/user'

  <Spoiler>No one can find me.</Spoiler> But I am exposed here.
  ```
</Fragment>
</MdxRepl>

### Formatted Date

<MdxRepl>
import { FormattedDate } from 'astro-pure/user'

<FormattedDate date={new Date('2021-08-01')} dateTimeOptions={{ month: 'short' }} />

<Fragment slot='desc'>
  ```jsx
  import { FormattedDate } from 'astro-pure/user'

  <FormattedDate date={new Date('2021-08-01')} dateTimeOptions={{ month: 'short' }} />
  ```
</Fragment>
</MdxRepl>

### Label

<MdxRepl>
import { Label } from 'astro-pure/user'

<Label title='Hello' />

<Fragment slot='desc'>
  ```jsx
  import { Label } from 'astro-pure/user'

  <Label title='Hello' />
  ```
</Fragment>
</MdxRepl>

### SVG Loader

<MdxRepl>
import { Svg } from 'astro-pure/user'

<Svg src={import('@/assets/icons/key.svg?raw')} />

<Fragment slot='desc'>
  ```jsx
  import { Svg } from 'astro-pure/user'

  <Svg src={import('@/assets/icons/key.svg?raw')} />
  ```
</Fragment>
</MdxRepl>

## Resources

### Icon

<MdxRepl width='100%'>
<div>
import { Icon } from 'astro-pure/user'

Single use: <Icon name='rss' class='inline' />

Preview all icons available (click button to copy):

import { Icons as allIcons } from 'astro-pure/libs'

<div class='flex flex-wrap gap-2'>
{
  Object.keys(allIcons).map(icon => {
    const script = `navigator.clipboard.writeText('${icon}');document.dispatchEvent(new CustomEvent('toast',{detail:{message:'Copied "${icon}" to clipboard!'}}))`
    return (
      <Button as='button' type='button' class='cursor-pointer' onClick={script}>
        <Icon slot='before' name={icon} />
        <span>{icon}</span>
      </Button>
    )
  })
}
</div>
</div>

<Fragment slot='desc'>
  ```jsx
  import { Icon } from 'astro-pure/user'

  Single use: <Icon name='rss' class='inline' />

  Preview all icons available (click button to copy):

  import { Icons as allIcons } from 'astro-pure/libs'
  import { Button } from 'astro-pure/user'

  <div class='flex flex-wrap gap-2'>
  {
    Object.keys(allIcons).map(icon => {
      const script = `navigator.clipboard.writeText('${icon}');document.dispatchEvent(new CustomEvent('toast',{detail:{message:'Copied "${icon}" to clipboard!'}}))`
      return (
        <Button as='button' type='button' class='cursor-pointer' onclick={script}>
          <Icon slot='before' name={icon} />
          <span>{icon}</span>
        </Button>
      )
    })
  }
  </div>
  ```
</Fragment>
</MdxRepl>

There's also some [Advanced Components](/docs/integrations/advanced), which may suit for you. Hope you enjoy using these components!
